home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / system-config-printer / monitor.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2009-10-12  |  19.3 KB  |  733 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. import cups
  5. import dbus
  6. import dbus.glib as dbus
  7. import gobject
  8. import time
  9. from debug import *
  10. import pprint
  11.  
  12. _ = lambda x: x
  13.  
  14. def set_gettext_function(x):
  15.     _ = x
  16.  
  17. import statereason
  18. from statereason import StateReason
  19. statereason.set_gettext_function(_)
  20. CONNECTING_TIMEOUT = 60
  21. MIN_REFRESH_INTERVAL = 1
  22.  
  23. def state_reason_is_harmless(reason):
  24.     if reason.startswith('moving-to-paused') and reason.startswith('paused') and reason.startswith('shutdown') and reason.startswith('stopping') or reason.startswith('stopped-partly'):
  25.         return True
  26.     return False
  27.  
  28.  
  29. def collect_printer_state_reasons(connection):
  30.     result = { }
  31.     
  32.     try:
  33.         printers = connection.getPrinters()
  34.     except cups.IPPError:
  35.         return result
  36.  
  37.     for name, printer in printers.iteritems():
  38.         reasons = printer['printer-state-reasons']
  39.         for reason in reasons:
  40.             if reason == 'none':
  41.                 break
  42.             
  43.             if state_reason_is_harmless(reason):
  44.                 continue
  45.             
  46.             if not result.has_key(name):
  47.                 result[name] = []
  48.             
  49.             result[name].append(StateReason(name, reason))
  50.         
  51.     
  52.     return result
  53.  
  54.  
  55. class Watcher:
  56.     
  57.     def monitor_exited(self, monitor):
  58.         debugprint(repr(monitor) + ' exited')
  59.  
  60.     
  61.     def state_reason_added(self, monitor, reason):
  62.         debugprint(repr(monitor) + ': +' + repr(reason))
  63.  
  64.     
  65.     def state_reason_removed(self, monitor, reason):
  66.         debugprint(repr(monitor) + ': -' + repr(reason))
  67.  
  68.     
  69.     def still_connecting(self, monitor, reason):
  70.         debugprint(repr(monitor) + ": `%s' still connecting" % reason.get_printer())
  71.  
  72.     
  73.     def now_connected(self, monitor, printer):
  74.         debugprint(repr(monitor) + ": `%s' now connected" % printer)
  75.  
  76.     
  77.     def current_printers_and_jobs(self, monitor, printers, jobs):
  78.         debugprint(repr(monitor) + ': printers and jobs lists provided')
  79.  
  80.     
  81.     def job_added(self, monitor, jobid, eventname, event, jobdata):
  82.         debugprint(repr(monitor) + ': job %d added' % jobid)
  83.  
  84.     
  85.     def job_event(self, monitor, jobid, eventname, event, jobdata):
  86.         debugprint(repr(monitor) + ": job %d has event `%s'" % (jobid, eventname))
  87.  
  88.     
  89.     def job_removed(self, monitor, jobid, eventname, event):
  90.         debugprint(repr(monitor) + ': job %d removed' % jobid)
  91.  
  92.     
  93.     def printer_added(self, monitor, printer):
  94.         debugprint(repr(monitor) + ": printer `%s' added" % printer)
  95.  
  96.     
  97.     def printer_event(self, monitor, printer, eventname, event):
  98.         debugprint(repr(monitor) + ": printer `%s' has event `%s'" % (printer, eventname))
  99.  
  100.     
  101.     def printer_removed(self, monitor, printer):
  102.         debugprint(repr(monitor) + ": printer `%s' removed" % printer)
  103.  
  104.     
  105.     def cups_connection_error(self, monitor):
  106.         debugprint(repr(monitor) + ': CUPS connection error')
  107.  
  108.     
  109.     def cups_ipp_error(self, monitor, e, m):
  110.         debugprint(repr(monitor) + ': CUPS IPP error (%d, %s)' % (e, repr(m)))
  111.  
  112.  
  113.  
  114. class Monitor:
  115.     DBUS_PATH = '/com/redhat/PrinterSpooler'
  116.     DBUS_IFACE = 'com.redhat.PrinterSpooler'
  117.     
  118.     def __init__(self, watcher, bus = None, my_jobs = True, specific_dests = None, monitor_jobs = True, host = None, port = None, encryption = None):
  119.         self.watcher = watcher
  120.         self.my_jobs = my_jobs
  121.         self.specific_dests = specific_dests
  122.         self.monitor_jobs = monitor_jobs
  123.         self.jobs = { }
  124.         self.printer_state_reasons = { }
  125.         self.printers = set()
  126.         self.process_pending_events = True
  127.         self.fetch_jobs_timer = None
  128.         if host:
  129.             cups.setServer(host)
  130.         
  131.         if port:
  132.             cups.setPort(port)
  133.         
  134.         if encryption:
  135.             cups.setEncryption(encryption)
  136.         
  137.         self.user = cups.getUser()
  138.         self.host = cups.getServer()
  139.         self.port = cups.getPort()
  140.         self.encryption = cups.getEncryption()
  141.         self.which_jobs = 'not-completed'
  142.         self.reasons_seen = { }
  143.         self.connecting_timers = { }
  144.         self.still_connecting = set()
  145.         self.connecting_to_device = { }
  146.         self.received_any_dbus_signals = False
  147.         if bus == None:
  148.             
  149.             try:
  150.                 bus = dbus.SystemBus()
  151.             except dbus.exceptions.DBusException:
  152.                 pass
  153.             except:
  154.                 None<EXCEPTION MATCH>dbus.exceptions.DBusException
  155.             
  156.  
  157.         None<EXCEPTION MATCH>dbus.exceptions.DBusException
  158.         if bus != None:
  159.             bus.add_signal_receiver(self.handle_dbus_signal, path = self.DBUS_PATH, dbus_interface = self.DBUS_IFACE)
  160.             self.bus = bus
  161.         
  162.         self.sub_id = -1
  163.         self.refresh()
  164.  
  165.     
  166.     def get_jobs(self):
  167.         return self.jobs.copy()
  168.  
  169.     
  170.     def cleanup(self):
  171.         if self.sub_id != -1:
  172.             user = cups.getUser()
  173.             
  174.             try:
  175.                 cups.setUser(self.user)
  176.                 c = cups.Connection(host = self.host, port = self.port, encryption = self.encryption)
  177.                 c.cancelSubscription(self.sub_id)
  178.                 debugprint('Canceled subscription %d' % self.sub_id)
  179.             except:
  180.                 pass
  181.  
  182.             cups.setUser(user)
  183.         
  184.         if self.bus != None:
  185.             self.bus.remove_signal_receiver(self.handle_dbus_signal, path = self.DBUS_PATH, dbus_interface = self.DBUS_IFACE)
  186.         
  187.         timers = self.connecting_timers.values()
  188.         for timer in [
  189.             self.update_timer,
  190.             self.fetch_jobs_timer]:
  191.             if timer:
  192.                 timers.append(timer)
  193.                 continue
  194.         
  195.         for timer in timers:
  196.             gobject.source_remove(timer)
  197.         
  198.         self.watcher.monitor_exited(self)
  199.  
  200.     
  201.     def set_process_pending(self, whether):
  202.         self.process_pending_events = whether
  203.  
  204.     
  205.     def check_still_connecting(self, printer):
  206.         '''Timer callback to check on connecting-to-device reasons.'''
  207.         if not self.process_pending_events:
  208.             timer = gobject.timeout_add(200, self.check_still_connecting, printer)
  209.             self.connecting_timers[printer] = timer
  210.             return False
  211.         del self.connecting_timers[printer]
  212.         debugprint("Still-connecting timer fired for `%s'" % printer)
  213.         (printer_jobs, my_printers) = self.sort_jobs_by_printer()
  214.         self.update_connecting_devices(printer_jobs)
  215.         return False
  216.  
  217.     
  218.     def update_connecting_devices(self, printer_jobs = { }):
  219.         '''Updates connecting_to_device dict and still_connecting set.'''
  220.         time_now = time.time()
  221.         connecting_to_device = { }
  222.         trouble = False
  223.         for printer, reasons in self.printer_state_reasons.iteritems():
  224.             connected = True
  225.             for reason in reasons:
  226.                 if reason.get_reason() == 'connecting-to-device':
  227.                     have_processing_job = False
  228.                     for job, data in printer_jobs.get(printer, { }).iteritems():
  229.                         state = data.get('job-state', cups.IPP_JOB_CANCELED)
  230.                         if state == cups.IPP_JOB_PROCESSING:
  231.                             have_processing_job = True
  232.                             break
  233.                             continue
  234.                     
  235.                     if not have_processing_job:
  236.                         debugprint('Ignoring stale connecting-to-device x')
  237.                         continue
  238.                     
  239.                     printer = reason.get_printer()
  240.                     t = self.connecting_to_device.get(printer, time_now)
  241.                     connecting_to_device[printer] = t
  242.                     debugprint('Connecting time: %d' % (time_now - t))
  243.                     if time_now - t >= CONNECTING_TIMEOUT:
  244.                         if have_processing_job:
  245.                             if printer not in self.still_connecting:
  246.                                 self.still_connecting.add(printer)
  247.                                 self.watcher.still_connecting(self, reason)
  248.                             
  249.                             if self.connecting_timers.has_key(printer):
  250.                                 gobject.source_remove(self.connecting_timers[printer])
  251.                                 del self.connecting_timers[printer]
  252.                                 debugprint("Stopped connecting timer for `%s'" % printer)
  253.                             
  254.                         
  255.                     
  256.                     connected = False
  257.                     break
  258.                     continue
  259.             
  260.             if connected and self.connecting_timers.has_key(printer):
  261.                 gobject.source_remove(self.connecting_timers[printer])
  262.                 del self.connecting_timers[printer]
  263.                 debugprint("Stopped connecting timer for `%s'" % printer)
  264.                 continue
  265.         
  266.         remove = set()
  267.         for printer in self.still_connecting:
  268.             if not connecting_to_device.has_key(printer):
  269.                 remove.add(printer)
  270.                 self.watcher.now_connected(self, printer)
  271.                 if self.connecting_timers.has_key(printer):
  272.                     gobject.source_remove(self.connecting_timers[printer])
  273.                     del self.connecting_timers[printer]
  274.                     debugprint("Stopped connecting timer for `%s'" % printer)
  275.                 
  276.             self.connecting_timers.has_key(printer)
  277.         
  278.         self.still_connecting = self.still_connecting.difference(remove)
  279.         self.connecting_to_device = connecting_to_device
  280.  
  281.     
  282.     def check_state_reasons(self, my_printers = set(), printer_jobs = { }):
  283.         old_reasons_seen_keys = self.reasons_seen.keys()
  284.         reasons_now = set()
  285.         for printer, reasons in self.printer_state_reasons.iteritems():
  286.             for reason in reasons:
  287.                 tuple = reason.get_tuple()
  288.                 printer = reason.get_printer()
  289.                 reasons_now.add(tuple)
  290.                 if not self.reasons_seen.has_key(tuple):
  291.                     self.watcher.state_reason_added(self, reason)
  292.                     self.reasons_seen[tuple] = reason
  293.                 
  294.                 if reason.get_reason() == 'connecting-to-device' and not self.connecting_to_device.has_key(printer):
  295.                     have_processing_job = False
  296.                     for job, data in printer_jobs.get(printer, { }).iteritems():
  297.                         state = data.get('job-state', cups.IPP_JOB_CANCELED)
  298.                         if state == cups.IPP_JOB_PROCESSING:
  299.                             have_processing_job = True
  300.                             break
  301.                             continue
  302.                     
  303.                 None if have_processing_job else get_debugging()
  304.             
  305.         
  306.         self.update_connecting_devices(printer_jobs)
  307.         items = self.reasons_seen.keys()
  308.         for tuple in items:
  309.             if tuple not in reasons_now:
  310.                 reason = self.reasons_seen[tuple]
  311.                 del self.reasons_seen[tuple]
  312.                 self.watcher.state_reason_removed(self, reason)
  313.                 continue
  314.         
  315.  
  316.     
  317.     def get_notifications(self):
  318.         if not self.process_pending_events:
  319.             gobject.source_remove(self.update_timer)
  320.             self.update_timer = gobject.timeout_add(200, self.get_notifications)
  321.             return False
  322.         debugprint('get_notifications')
  323.         user = cups.getUser()
  324.         
  325.         try:
  326.             cups.setUser(self.user)
  327.             c = cups.Connection(host = self.host, port = self.port, encryption = self.encryption)
  328.             
  329.             try:
  330.                 
  331.                 try:
  332.                     notifications = c.getNotifications([
  333.                         self.sub_id], [
  334.                         self.sub_seq + 1])
  335.                 except AttributeError:
  336.                     self.process_pending_events
  337.                     self.process_pending_events
  338.                     notifications = c.getNotifications([
  339.                         self.sub_id])
  340.                 except:
  341.                     self.process_pending_events
  342.  
  343.             except cups.IPPError:
  344.                 self.process_pending_events
  345.                 (e, m) = self.process_pending_events
  346.                 cups.setUser(user)
  347.                 if e == cups.IPP_NOT_FOUND:
  348.                     self.sub_id = -1
  349.                     self.refresh()
  350.                     return False
  351.                 self.watcher.cups_ipp_error(self, e, m)
  352.                 return True
  353.                 e == cups.IPP_NOT_FOUND
  354.  
  355.         except RuntimeError:
  356.             self.process_pending_events
  357.             self.process_pending_events
  358.             cups.setUser(user)
  359.             self.watcher.cups_connection_error(self)
  360.             return True
  361.  
  362.         cups.setUser(user)
  363.         deferred_calls = []
  364.         jobs = self.jobs.copy()
  365.         for event in notifications['events']:
  366.             seq = event['notify-sequence-number']
  367.             self.sub_seq = seq
  368.             nse = event['notify-subscribed-event']
  369.             debugprint('%d %s %s' % (seq, nse, event['notify-text']))
  370.             if get_debugging():
  371.                 debugprint(pprint.pformat(event))
  372.             
  373.             if nse.startswith('printer-'):
  374.                 name = event['printer-name']
  375.                 if nse == 'printer-added' and name not in self.printers:
  376.                     self.printers.add(name)
  377.                     deferred_calls.append((self.watcher.printer_added, (self, name)))
  378.                     continue
  379.                 if nse == 'printer-deleted' and name in self.printers:
  380.                     self.printers.remove(name)
  381.                     items = self.reasons_seen.keys()
  382.                     for tuple in items:
  383.                         if tuple[1] == name:
  384.                             reason = self.reasons_seen[tuple]
  385.                             del self.reasons_seen[tuple]
  386.                             deferred_calls.append((self.watcher.state_reason_removed, (self, reason)))
  387.                             continue
  388.                     
  389.                     if self.printer_state_reasons.has_key(name):
  390.                         del self.printer_state_reasons[name]
  391.                     
  392.                     deferred_calls.append((self.watcher.printer_removed, (self, name)))
  393.                     continue
  394.                 if name in self.printers:
  395.                     printer_state_reasons = event['printer-state-reasons']
  396.                     reasons = []
  397.                     for reason in printer_state_reasons:
  398.                         if reason == 'none':
  399.                             break
  400.                         
  401.                         if state_reason_is_harmless(reason):
  402.                             continue
  403.                         
  404.                         reasons.append(StateReason(name, reason))
  405.                     
  406.                     self.printer_state_reasons[name] = reasons
  407.                     deferred_calls.append((self.watcher.printer_event, (self, name, nse, event)))
  408.                     continue
  409.                 continue
  410.             
  411.             jobid = event['notify-job-id']
  412.             if (nse == 'job-created' or nse == 'job-state-changed') and not jobs.has_key(jobid) and event['job-state'] == cups.IPP_JOB_PROCESSING:
  413.                 if self.specific_dests != None and event['printer-name'] not in self.specific_dests:
  414.                     continue
  415.                 
  416.                 
  417.                 try:
  418.                     attrs = c.getJobAttributes(jobid)
  419.                     if self.my_jobs and attrs['job-originating-user-name'] != cups.getUser():
  420.                         continue
  421.                     
  422.                     jobs[jobid] = attrs
  423.                 except AttributeError:
  424.                     jobs[jobid] = {
  425.                         'job-k-octets': 0 }
  426.                 except cups.IPPError:
  427.                     (e, m) = None
  428.                     self.watcher.cups_ipp_error(self, e, m)
  429.                     jobs[jobid] = {
  430.                         'job-k-octets': 0 }
  431.  
  432.                 deferred_calls.append((self.watcher.job_added, (self, jobid, nse, event, jobs[jobid].copy())))
  433.             elif (nse == 'job-completed' or nse == 'job-state-changed') and event['job-state'] == cups.IPP_JOB_COMPLETED:
  434.                 if self.which_jobs not in ('completed', 'all'):
  435.                     
  436.                     try:
  437.                         del jobs[jobid]
  438.                         deferred_calls.append((self.watcher.job_removed, (self, jobid, nse, event)))
  439.                     continue
  440.                     except KeyError:
  441.                         continue
  442.                     
  443.  
  444.                 
  445.             
  446.             
  447.             try:
  448.                 job = jobs[jobid]
  449.             except KeyError:
  450.                 continue
  451.  
  452.             for attribute in [
  453.                 'job-state',
  454.                 'job-name']:
  455.                 job[attribute] = event[attribute]
  456.             
  457.             if event.has_key('notify-printer-uri'):
  458.                 job['job-printer-uri'] = event['notify-printer-uri']
  459.             
  460.             deferred_calls.append((self.watcher.job_event, (self, jobid, nse, event, job.copy())))
  461.         
  462.         self.set_process_pending(False)
  463.         self.update_jobs(jobs)
  464.         self.jobs = jobs
  465.         for fn, args in deferred_calls:
  466.             fn(*args)
  467.         
  468.         self.set_process_pending(True)
  469.         if not self.received_any_dbus_signals:
  470.             gobject.source_remove(self.update_timer)
  471.             interval = 1000 * notifications['notify-get-interval']
  472.             self.update_timer = gobject.timeout_add(interval, self.get_notifications)
  473.         
  474.         return False
  475.  
  476.     
  477.     def refresh(self, which_jobs = None, refresh_all = True):
  478.         debugprint('refresh')
  479.         if which_jobs != None:
  480.             self.which_jobs = which_jobs
  481.         
  482.         user = cups.getUser()
  483.         
  484.         try:
  485.             cups.setUser(self.user)
  486.             c = cups.Connection(host = self.host, port = self.port, encryption = self.encryption)
  487.         except RuntimeError:
  488.             self.watcher.cups_connection_error(self)
  489.             cups.setUser(user)
  490.             return None
  491.  
  492.         if self.sub_id != -1:
  493.             
  494.             try:
  495.                 c.cancelSubscription(self.sub_id)
  496.             except cups.IPPError:
  497.                 (e, m) = None
  498.                 self.watcher.cups_ipp_error(self, e, m)
  499.  
  500.             gobject.source_remove(self.update_timer)
  501.             debugprint('Canceled subscription %d' % self.sub_id)
  502.         
  503.         
  504.         try:
  505.             del self.sub_seq
  506.         except AttributeError:
  507.             pass
  508.  
  509.         events = [
  510.             'printer-added',
  511.             'printer-deleted',
  512.             'printer-state-changed']
  513.         if self.monitor_jobs:
  514.             events.extend([
  515.                 'job-created',
  516.                 'job-completed',
  517.                 'job-stopped',
  518.                 'job-state-changed'])
  519.         
  520.         
  521.         try:
  522.             self.sub_id = c.createSubscription('/', events = events)
  523.         except cups.IPPError:
  524.             (e, m) = None
  525.             self.watcher.cups_ipp_error(self, e, m)
  526.  
  527.         cups.setUser(user)
  528.         self.update_timer = gobject.timeout_add(MIN_REFRESH_INTERVAL * 1000, self.get_notifications)
  529.         debugprint('Created subscription %d' % self.sub_id)
  530.         if self.monitor_jobs:
  531.             jobs = self.jobs.copy()
  532.             if self.which_jobs not in ('all', 'completed'):
  533.                 filtered = { }
  534.                 for jobid, job in jobs.iteritems():
  535.                     if job['job-state'] < cups.IPP_JOB_CANCELED:
  536.                         filtered[jobid] = job
  537.                         continue
  538.                 
  539.                 jobs = filtered
  540.             
  541.             self.fetch_first_job_id = 1
  542.             if self.fetch_jobs_timer:
  543.                 gobject.source_remove(self.fetch_jobs_timer)
  544.             
  545.             self.fetch_jobs_timer = gobject.timeout_add(5, self.fetch_jobs, refresh_all)
  546.         else:
  547.             jobs = { }
  548.         
  549.         try:
  550.             self.printer_state_reasons = collect_printer_state_reasons(c)
  551.             dests = c.getPrinters()
  552.             self.printers = set(dests.keys())
  553.         except cups.IPPError:
  554.             (e, m) = None
  555.             self.watcher.cups_ipp_error(self, e, m)
  556.             return None
  557.             except RuntimeError:
  558.                 self.watcher.cups_connection_error(self)
  559.                 return None
  560.             elif self.specific_dests != None:
  561.                 for jobid in jobs.keys():
  562.                     uri = jobs[jobid].get('job-printer-uri', '/')
  563.                     i = uri.rfind('/')
  564.                     printer = uri[i + 1:]
  565.                     if printer not in self.specific_dests:
  566.                         del jobs[jobid]
  567.                         continue
  568.                 
  569.             
  570.  
  571.         self.set_process_pending(False)
  572.         self.watcher.current_printers_and_jobs(self, self.printers.copy(), jobs.copy())
  573.         self.update_jobs(jobs)
  574.         self.jobs = jobs
  575.         self.set_process_pending(True)
  576.         return False
  577.  
  578.     
  579.     def fetch_jobs(self, refresh_all):
  580.         if not self.process_pending_events:
  581.             return True
  582.         user = cups.getUser()
  583.         
  584.         try:
  585.             cups.setUser(self.user)
  586.             c = cups.Connection(host = self.host, port = self.port, encryption = self.encryption)
  587.         except RuntimeError:
  588.             self.process_pending_events
  589.             self.process_pending_events
  590.             self.watcher.cups_connection_error(self)
  591.             self.fetch_jobs_timer = None
  592.             cups.setUser(user)
  593.             return False
  594.  
  595.         limit = 1
  596.         
  597.         try:
  598.             fetched = c.getJobs(which_jobs = self.which_jobs, my_jobs = self.my_jobs, first_job_id = self.fetch_first_job_id, limit = limit)
  599.         except cups.IPPError:
  600.             self.process_pending_events
  601.             (e, m) = self.process_pending_events
  602.             self.watcher.cups_ipp_error(self, e, m)
  603.             self.fetch_jobs_timer = None
  604.             cups.setUser(user)
  605.             return False
  606.  
  607.         cups.setUser(user)
  608.         got = len(fetched)
  609.         debugprint('Got %s jobs, asked for %s' % (got, limit))
  610.         deferred_calls = []
  611.         jobs = self.jobs.copy()
  612.         jobids = fetched.keys()
  613.         jobids.sort()
  614.         if got > 0:
  615.             last_jobid = jobids[got - 1]
  616.         else:
  617.             last_jobid = self.fetch_first_job_id + limit
  618.         for jobid in xrange(self.fetch_first_job_id, last_jobid + 1):
  619.             
  620.             try:
  621.                 job = fetched[jobid]
  622.                 if self.specific_dests != None:
  623.                     uri = job.get('job-printer-uri', '/')
  624.                     i = uri.rfind('/')
  625.                     printer = uri[i + 1:]
  626.                     if printer not in self.specific_dests:
  627.                         raise KeyError
  628.                     printer not in self.specific_dests
  629.                 
  630.                 if jobs.has_key(jobid):
  631.                     fn = self.watcher.job_event
  632.                 else:
  633.                     fn = self.watcher.job_added
  634.                 jobs[jobid] = job
  635.                 deferred_calls.append((fn, (self, jobid, '', { }, job.copy())))
  636.             continue
  637.             except KeyError:
  638.                 if jobs.has_key(jobid):
  639.                     del jobs[jobid]
  640.                     deferred_calls.append((self.watcher.job_removed, (self, jobid, '', { })))
  641.                 
  642.                 jobs.has_key(jobid)
  643.             
  644.  
  645.         
  646.         jobids = jobs.keys()
  647.         jobids.sort()
  648.         if got < limit:
  649.             trim = False
  650.             for i in range(len(jobids)):
  651.                 jobid = jobids[i]
  652.                 if not trim and jobid > last_jobid:
  653.                     trim = True
  654.                 
  655.                 if trim:
  656.                     del jobs[jobid]
  657.                     deferred_calls.append((self.watcher.job_removed, (self, jobid, '', { })))
  658.                     continue
  659.             
  660.         
  661.         self.update_jobs(jobs)
  662.         self.jobs = jobs
  663.         for fn, args in deferred_calls:
  664.             fn(*args)
  665.         
  666.         if got < limit:
  667.             self.fetch_jobs_timer = None
  668.             return False
  669.         next = jobid + 1
  670.         while not refresh_all and self.jobs.has_key(next):
  671.             next += 1
  672.             continue
  673.             got < limit
  674.         self.fetch_first_job_id = next
  675.         return True
  676.  
  677.     
  678.     def sort_jobs_by_printer(self, jobs = None):
  679.         if jobs == None:
  680.             jobs = self.jobs
  681.         
  682.         my_printers = set()
  683.         printer_jobs = { }
  684.         for job, data in jobs.iteritems():
  685.             state = data.get('job-state', cups.IPP_JOB_CANCELED)
  686.             if state >= cups.IPP_JOB_CANCELED:
  687.                 continue
  688.             
  689.             uri = data.get('job-printer-uri', '')
  690.             i = uri.rfind('/')
  691.             if i == -1:
  692.                 continue
  693.             
  694.             printer = uri[i + 1:]
  695.             my_printers.add(printer)
  696.             if not printer_jobs.has_key(printer):
  697.                 printer_jobs[printer] = { }
  698.             
  699.             printer_jobs[printer][job] = data
  700.         
  701.         return (printer_jobs, my_printers)
  702.  
  703.     
  704.     def update_jobs(self, jobs):
  705.         debugprint('update_jobs')
  706.         (printer_jobs, my_printers) = self.sort_jobs_by_printer(jobs)
  707.         self.check_state_reasons(my_printers, printer_jobs)
  708.  
  709.     
  710.     def update(self):
  711.         gobject.source_remove(self.update_timer)
  712.         self.update_timer = gobject.timeout_add(200, self.get_notifications)
  713.  
  714.     
  715.     def handle_dbus_signal(self, *args):
  716.         self.update()
  717.         if not self.received_any_dbus_signals:
  718.             self.received_any_dbus_signals = True
  719.         
  720.  
  721.  
  722. if __name__ == '__main__':
  723.     set_debugging(True)
  724.     m = Monitor(Watcher())
  725.     loop = gobject.MainLoop()
  726.     
  727.     try:
  728.         loop.run()
  729.     finally:
  730.         m.cleanup()
  731.  
  732.  
  733.